#include "render_object.h"
#include "shaders.h"
#include "mesh.h"

#include <iostream>
using namespace std;

RenderObject::RenderObject()
{
    pMatWorld = new Matrix4x4;
    pMatWorld->Identity();
}

int RenderObject::NewBuffer(int Attrib, int nCompNo, GLenum DataType)
{
	GLuint uNewBuffer;
	glGenBuffers(1, &uNewBuffer);

	Buffers.push_back(uNewBuffer);
	BufferTypes.push_back(Attrib);
	BufferComponentsNo.push_back(nCompNo);
	BufferDataType.push_back(DataType);

	return Buffers.size()-1;
}

void RenderObject::BufferData(int nBufferIndex, GLsizeiptr size, const GLvoid *data, GLenum Usage, int nVertexNo)
{
    nVerticesNo = nVertexNo;

    glBindBuffer(GL_ARRAY_BUFFER, Buffers[nBufferIndex]);
	glBufferData(GL_ARRAY_BUFFER, size, data, Usage);
}

void RenderObject::BindBuffers()
{
	for(unsigned int i = 0; i < Buffers.size(); ++i)
	{
		glBindBuffer(GL_ARRAY_BUFFER, Buffers[i]);
		glVertexAttribPointer(BufferTypes[i], BufferComponentsNo[i], BufferDataType[i], GL_FALSE, 0, 0);
	}
}

void RenderObject::BindSingleBuffer(int nWhich)
{
	glBindBuffer(GL_ARRAY_BUFFER, Buffers[nWhich]);
	glVertexAttribPointer(BufferTypes[nWhich], BufferComponentsNo[nWhich], BufferDataType[nWhich], GL_FALSE, 0, 0);
}

void RenderObject::EnableAttributes()
{
    for(unsigned int i = 0; i < BufferTypes.size(); ++i)
    {
        glEnableVertexAttribArray(BufferTypes[i]);
    }
}

void RenderObject::DisableAttributes()
{
    for(unsigned int i = 0; i < BufferTypes.size(); ++i)
    {
        glDisableVertexAttribArray(BufferTypes[i]);
    }
}

void RenderObject::UseMaterial()
{
    pMaterial->PassToShader(pShader);
}

void RenderObject::Render(GLint nPrimitiveType)
{
    pShader->SetMatrix4("inWorld", pMatWorld->GetTab());

    EnableAttributes();

    BindBuffers();

    glDrawArrays(nPrimitiveType, 0, nVerticesNo);

    DisableAttributes();
}

void RenderObject::SetWorldMatrix(Matrix4x4 *pNewMatrix)
{
    pMatWorld = pNewMatrix;
}

void RenderObject::SetMaterial(CMaterial *pNew)
{
    pMaterial =  pNew;
}

void RenderObject::SetShader(ShaderProgram *pNew)
{
    pShader = pNew;
}

void RenderObject::SetMesh(Mesh *pMesh)
{
    pMesh->PassToRenderObj(this);
}
